<!DOCTYPE html>
<html>
<head>
  <title>Relativity Diagram</title>
  <style>
    body {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
      background-color: #f0f0f0;
    }
    canvas {
      border: 1px solid #ccc;
      background-color: #ffffff;
    }
  </style>
</head>
<body>
  <canvas id="relativityCanvas" width="550" height="450"></canvas>
  <script>
    const canvas = document.getElementById('relativityCanvas');
    const ctx = canvas.getContext('2d');

    // Helper function to draw an arrow
    function drawArrow(ctx, fromx, fromy, tox, toy, headlen = 10) {
      const angle = Math.atan2(toy - fromy, tox - fromx);
      const headAngle = Math.PI / 6;
      ctx.save();
      ctx.beginPath();
      ctx.moveTo(fromx, fromy);
      ctx.lineTo(tox, toy);
      ctx.stroke();
      ctx.beginPath();
      ctx.moveTo(tox, toy);
      ctx.lineTo(tox - headlen * Math.cos(angle - headAngle), toy - headlen * Math.sin(angle - headAngle));
      ctx.lineTo(tox - headlen * Math.cos(angle + headAngle), toy - headlen * Math.sin(angle + headAngle));
      ctx.closePath();
      ctx.fill();
      ctx.restore();
    }

    // --- Main Drawing ---

    // Style and position settings
    ctx.strokeStyle = '#000000';
    ctx.fillStyle = '#000000';
    ctx.lineWidth = 1.5;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';

    const OX = 150, OY = 225;
    const OPrimeX = 250, OPrimeY = 225;

    // --- S frame ---
    // y-axis
    drawArrow(ctx, OX, OY + 200, OX, OY - 200);
    ctx.font = 'italic 20px Times New Roman';
    ctx.fillText('y', OX - 20, OY - 190);

    // x-axis (shared line)
    ctx.beginPath();
    ctx.moveTo(OX - 100, OY);
    ctx.lineTo(OPrimeX + 280, OY);
    ctx.stroke();

    // Origin O
    ctx.beginPath();
    ctx.arc(OX, OY, 4, 0, 2 * Math.PI);
    ctx.fill();
    ctx.fillText('O', OX, OY + 20);

    // Label for S frame
    ctx.font = '24px "Times New Roman"';
    ctx.fillText('S系', OX - 50, OY - 150);

    // --- S' frame ---
    // y'-axis
    drawArrow(ctx, OPrimeX, OPrimeY + 200, OPrimeX, OPrimeY - 200);
    ctx.font = 'italic 20px Times New Roman';
    ctx.fillText("y'", OPrimeX + 20, OPrimeY - 190);

    // Origin O'
    ctx.beginPath();
    ctx.arc(OPrimeX, OPrimeY, 4, 0, 2 * Math.PI);
    ctx.fill();
    ctx.fillText("O'", OPrimeX, OPrimeY + 20);

    // Label for S' frame
    ctx.font = '24px "Times New Roman"';
    ctx.fillText("S'系", OPrimeX + 80, OY - 150);

    // --- Shared X-Axis details ---
    // Small arrows on x-axis
    ctx.lineWidth = 1;
    drawArrow(ctx, OPrimeX + 100, OY, OPrimeX + 130, OY, 6);
    drawArrow(ctx, OPrimeX + 160, OY, OPrimeX + 190, OY, 6);
    ctx.lineWidth = 1.5;
    
    // Labels x and x'
    ctx.font = 'italic 20px Times New Roman';
    ctx.fillText('x', OPrimeX + 145, OY + 20);
    ctx.fillText("x'", OPrimeX + 205, OY + 20);

    // Velocity vector v
    const vY = OY - 40;
    drawArrow(ctx, OPrimeX + 80, vY, OPrimeX + 180, vY);
    ctx.fillText('v', OPrimeX + 130, vY - 15);

    // --- Particles and Accelerations in S' frame ---
    const particleYDist = 70;
    const aArrowYDist = 35; // Position of the acceleration arrow's center from O'
    const aArrowLen = 30;

    // Particle A
    ctx.beginPath();
    ctx.arc(OPrimeX, OPrimeY - particleYDist, 3, 0, 2 * Math.PI);
    ctx.fill();
    ctx.textAlign = 'left';
    ctx.fillText('A', OPrimeX + 10, OPrimeY - particleYDist);

    // Acceleration for A (upward)
    const aArrowAY = OPrimeY - aArrowYDist;
    drawArrow(ctx, OPrimeX, aArrowAY + aArrowLen / 2, OPrimeX, aArrowAY - aArrowLen / 2, 8);
    ctx.textAlign = 'right';
    ctx.fillText('a', OPrimeX - 10, aArrowAY - 2);
    ctx.font = 'italic 14px Times New Roman';
    ctx.fillText('0', OPrimeX - 3, aArrowAY + 5);
    ctx.font = 'italic 20px Times New Roman';

    // Particle B
    ctx.beginPath();
    ctx.arc(OPrimeX, OPrimeY + particleYDist, 3, 0, 2 * Math.PI);
    ctx.fill();
    ctx.textAlign = 'left';
    ctx.fillText('B', OPrimeX + 10, OPrimeY + particleYDist);

    // Acceleration for B (downward)
    const aArrowBY = OPrimeY + aArrowYDist;
    drawArrow(ctx, OPrimeX, aArrowBY - aArrowLen / 2, OPrimeX, aArrowBY + aArrowLen / 2, 8);
    ctx.textAlign = 'right';
    ctx.fillText('a', OPrimeX - 10, aArrowBY - 2);
    ctx.font = 'italic 14px Times New Roman';
    ctx.fillText('0', OPrimeX - 3, aArrowBY + 5);
  </script>
</body>
</html>